<template>
  <div class="editor-container" v-loading="loading">
    <Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
    <Editor :mode="mode" :defaultConfig="editorConfig" :style="{ height }" v-model="htmlValue"
      @onCreated="handleCreated" @onChange="handleChange" />
  </div>
</template>

<script setup lang="ts">
// 基于wangeditor的富文本组件，支持图片，视频的自定义上传和网络地址插入，自定义附件上传
defineOptions({
  name: 'MkRichTextEditor'
})

// wangeditor
import '@wangeditor/editor/dist/css/style.css';
import { IDomEditor, IToolbarConfig, IEditorConfig } from '@wangeditor/editor';
import { Toolbar, Editor } from '@wangeditor/editor-for-vue';

import { reactive, shallowRef, watch, onBeforeUnmount, ref } from 'vue';
import { ElMessage } from 'element-plus';
// 业务
import { getAPI } from '/@/utils/axios-utils';
import { SysFileApi } from '/@/api-services/api';

// prop
const props = withDefaults(defineProps<{
  isDisabled?: boolean,
  placeholder?: string,
  mode?: string,
  height?: string,
}>(), {
  isDisabled: false,  // 是否禁用
  placeholder: '请输入内容...',  // 内容框默认 placeholder
  mode: 'default', // 模式
  height: '60vh',  // 高度
})

// watch
watch(
  () => props.isDisabled,
  (bool) => {
    const editor = editorRef.value;
    if (editor == null) return;
    bool ? editor.disable() : editor.enable();
  }
);

const loading = ref(false)

// vue3.4以上
const htmlValue = defineModel('htmlValue', { required: true, default: '' })

// 定义变量内容
const editorRef = shallowRef();
// 工具栏配置
const toolbarConfig = ref({
  insertKeys: {
    index: 21, // 自定义插入的位置
    keys: ['uploadAttachment'], // “上传附件”菜单
  },
},)

// 编辑器配置
const editorConfig = ref({
  // placeholder
  placeholder: props.placeholder,
  // “下载附件”菜单
  hoverbarKeys: {
    attachment: {
      menuKeys: ['downloadAttachment'],
    },
  },
  // 菜单配置
  MENU_CONF: {
    // 上传图片
    uploadImage: {
      customUpload: async (file: File, insertFn: (url: string, alt: string, href: string) => void) => {
        const result = await uploadFile(file)
        insertFn(result?.url!, result?.fileName!, result?.url!);
      },
    },
    // 插入图片
    insertImage: {
      checkImage(src: string, alt: string, href: string): boolean | string | undefined {
        // 返回值有三种选择：
        // 1. 返回 true ，说明检查通过，编辑器将正常插入视频
        // 2. 返回一个字符串，说明检查未通过，编辑器会阻止插入。会 alert 出错误信息（即返回的字符串）
        // 3. 返回 undefined（即没有任何返回），说明检查未通过，编辑器会阻止插入。但不会提示任何信息
        return checkUrl(src, '图片')
      },
    },

    // 插入视频
    insertVideo: {
      checkVideo(src: string, poster: string): boolean | string | undefined {
        return checkUrl(src, '视频')
      }
    },

    // 上传视频
    uploadVideo: {
      customUpload: async (file: File, insertFn: (url: string, poster: string) => void) => {
        const result = await uploadFile(file)
        insertFn(result?.url!, '');
      },
    },

    // 上传附件
    uploadAttachment: {
      customUpload: async (file: File, insertFn: Function) => {
        const result = await uploadFile(file)
        insertFn(result?.fileName!, result?.url!);
      },
    }
  },
})

const checkUrl = (src: string, type: string) => {
  if (!src) {
    return
  }
  if (src.indexOf('http') !== 0) {
    // 这里没有像官网说的会alert，先用element的提示
    ElMessage.error(`${type}网址必须以 http/https 开头`)
    return `${type}网址必须以 http/https 开头`;
  }
  return true;
}

const uploadFile = async (file: File) => {
  try {
    loading.value = true
    const { data } = await getAPI(SysFileApi).apiSysFileUploadFilePostForm(file);
    if (data.type == 'success' && data.result != null) {
      return data.result
    }
  } finally {
    loading.value = false
  }

}

// 编辑器创建回调函数
const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor;
};

// 编辑器内容改变时
const handleChange = (editor: IDomEditor) => {
  htmlValue.value = editor.getHtml();
};

// 页面销毁时
onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});

</script>
